﻿using System;
using System.IO;
using System.Threading.Tasks;
using System.Xml.Serialization;
using UnityEngine;//只用来Log

namespace YeqianFramework.common
{
	public static class XmlHelper
	{
		#region XMl --> 对象
		/// <summary>
		/// 同步 加载XML
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="path">xml路径</param>
		/// <returns></returns>
		private static T Xml2Object<T>(string path)
		{
			T ret = default;
			using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
			{
				XmlSerializer xs = new XmlSerializer(typeof(T));
				try
				{
					ret = (T)xs.Deserialize(fs);
				}
				catch (Exception e)
				{
					Debug.LogError("XML 反序列化失败 ：" + path + "\r\n" + e.Message);
					throw;
				}
			}
			return ret;
		}
		/// <summary>
		/// 同步 加载XML
		/// </summary>
		/// <param name="path"></param>
		/// <param name="type">返回的对象应该是什么类型的</param>
		/// <returns></returns>
		private static object Xml2Object(string path, Type type)
		{
			object ret = null;
			using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
			{
				XmlSerializer xs = new XmlSerializer(type);
				try
				{
					ret = xs.Deserialize(fs);
				}
				catch (Exception e)
				{
					Debug.LogError("XML 反序列化失败 ：" + path + "\r\n" + e.Message);
					throw;
				}
			}
			return ret;
		}

		#region 异步加载
		/// <summary>
		/// 异步 加载XML
		/// </summary>
		/// <typeparam name="T">这个返回对象应该是什么类型的</typeparam>
		/// <param name="path"></param>
		/// <param name="onComplete">完成时候的回调，形参是 T 类型的</param>
		public static async void Xml2ObjectAsync<T>(string path, Action<object> onComplete)
		{
			T ret = await Task.Run(() =>
			{
				return Xml2Object<T>(path);
			});
			onComplete?.Invoke(ret);
		}
		/// <summary>
		/// 异步 加载XML
		/// </summary>
		/// <param name="path"></param>
		/// <param name="type">返回的回调当中，形参应该是什么类型的</param>
		/// <param name="onComplete">完成时候的回调，形参是 T 类型的</param>
		public static async void Xml2ObjectAsync(string path, Type type, Action<object> onComplete)
		{
			object ret = await Task.Run(() =>
			{
				return Xml2Object(path, type);
			});
			onComplete?.Invoke(ret);
		}
		#endregion

		#endregion

		//---------------------------------------------------------------------------------------------------------------------------------------

		#region 对象 --> XML
		/// <summary>
		/// 对象转XML
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="path">xml路径</param>
		/// <param name="obj"></param>
		private static void Object2Xml<T>(string path, T obj)
		{
			using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
			{
				XmlSerializer xs = new XmlSerializer(obj.GetType());
				try
				{
					xs.Serialize(fs, obj);
				}
				catch (Exception e)
				{
					Debug.LogError("XML序列化失败 ：" + path + "\r\n" + e.Message);
					throw;
				}
			}
		}

		#region 异步保存
		/// <summary>
		/// 异步 保存数据到XML
		/// </summary>
		/// <typeparam name="T">要序列化什么类型</typeparam>
		/// <param name="path"></param>
		/// <param name="obj"></param>
		/// <param name="onComplete">完成时候的回调</param>
		public static async void Object2XmlAsync<T>(string path, T obj, Action onComplete)
		{
			await Task.Run(() =>
			{
				Object2Xml(path, obj);
			});
			onComplete?.Invoke();
		}
		#endregion

		#endregion

		//---------------------------------------------------------------------------------------------------------------------------------------

		public static int String2Int(string val)
		{
			int resultVal = 0;
			if (!int.TryParse(val, out resultVal))
			{
				YQLogCenter.Current.LogError(string.Format("参数值 {0} 无法转换为整数", val));
				return 0;
			}
			return resultVal;
		}
	}

	/// <summary>
	/// 异步加载XML的时候给另一个线程传递的参数
	/// </summary>
	class Xml2ObjAsyncParameter
	{
		public string filePath;
		public Action<object> onComplete;
		public Type type;

		public Xml2ObjAsyncParameter(string filePath, Action<object> callback)
		{
			this.filePath = filePath;
			this.onComplete = callback;
		}
		public Xml2ObjAsyncParameter(string filePath, Action<object> callback, Type type) : this(filePath, callback)
		{
			this.type = type;
		}
	}

	/// <summary>
	/// 异步存储XML的时候给另一个线程传递的参数
	/// </summary>
	class Obj2XmlAsyncParameter
	{
		public string filePath;
		public object obj;
		public Action onComplete;

		public Obj2XmlAsyncParameter(string filePath, object obj)
		{
			this.filePath = filePath;
			this.obj = obj;
		}

		public Obj2XmlAsyncParameter(string filePath, object obj, Action onComplete) : this(filePath, obj)
		{
			this.onComplete = onComplete;
		}
	}
}
